iT邦幫忙

2023 iThome 鐵人賽

DAY 21
1
Modern Web

30天React練功坊-攻克常見實務/面試問題系列 第 21

30天React練功坊-攻克常見實務/面試問題 Day21: React render logic interview question

  • 分享至 

  • xImage
  •  
tags: ItIron2023 react

前言

我們昨天看了最後一個關於實務上常碰到的issue,剩下的10天我們將進入react coding interview questions,多半是來自我實際面試時碰到的問題或是其觀念延伸,問題並不算太難,主要是針對jr等級的react developer,強烈建議各位在進入這個系列前可以先確保自己已經對過去20天我們探討的所有議題都有所了解,接下來會是一些綜合應用的部分,一樣都會透過一些類實務的情境測試你對React的了解,差別在於你現在多半不是要去解決某個bug,而是去達成一些商業需求或是根據程式碼回答指定的問題,準備好的話我們就開始吧! 不用擔心,今天的問題是個暖手的好機會!

本日題目

請你觀察這個codesandbox以及下方的程式碼,在這份程式碼中我們塞了數個console.log,請回答在下列情況下,console中看到的log順序為何

import React, { useState, useEffect } from "react";

function App() {
  const [count, setCount] = useState(0);

  console.log("A");

  useEffect(() => {
    console.log("B");
    return () => {
      console.log("C");
    };
  }, []);

  console.log("D");

  useEffect(() => {
    console.log("E");
  });

  useEffect(() => {
    console.log("F");
  }, [count]);

  const increment = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={increment}>Increment</button>
    </div>
  );
}

1. 畫面第一次載入後
2. 點擊按鈕後

解答與基本解釋

好了,作為練手這是個不錯的問題,當時這個題目來自在當時一家新創美商的面試,可以測試你對於react render邏輯的了解程度,首先要回答這個問題之前你需要先確認一件重要的事,這份程式碼是在什麼環境下執行的、是否有在StrictMode下,先確認這一點之後你才有辦法正確的回答這個問題。
我們在Day10曾經提過這個議題,React在StrictMode下為了協助你確認是否有意料外的side effect會執行你的hooks兩次,這會讓結果與我們預期的有些不同! 因此以下我們先以非StrictMode的前提下討論,我們先看一下第一次載入的情況。

第一次載入

首先我們知道useEffect會在render畫面後執行,所以一切與useEffect有關的都可以先當作沒看到,最先執行的會是

console.log("A");
console.log("D");

接著我們來處理useEffect的部分

useEffect(() => {
  console.log("B");
  return () => {
    console.log("C");
  };
}, []);


useEffect(() => {
  console.log("E");
});

useEffect(() => {
  console.log("F");
}, [count]);

分別來看三個useEffect吧,我們都知道useEffect在第一次render時都必定會執行,因此下方的程式碼會執行

console.log("B");
console.log("E");
console.log("F");

最終你在第一次render看到的會是

A
D
B
E
F

接著我們來處理比較容易有爭議的第二個情況

點擊按鈕後

同步的部分還是跟剛剛一樣,下方的程式碼仍會先執行

console.log("A");
console.log("D");

關鍵在於useEffect的處理,首先你應該知道下方這個不會執行,因為它有個空的dependency array,也就是只會在第一次渲染時執行callback,同時cleanup function僅會在組件unmount或是dependency array的值有更新才會執行,因此最終B & C都不會出現在結果中

useEffect(() => {
  console.log("B");
  return () => {
    console.log("C");
  };
}, []);

接著我們看一下另外兩個useEffect的dependency array,當沒有任何dependency array時表示每次re-render都會執行,而[count]表示count有更新時就會執行,所以下方兩個effect都會再次被執行

useEffect(() => {
  console.log("E");
});

useEffect(() => {
  console.log("F");
}, [count]);

最終你看到的結果是

A
D
E
F

總結

今天我們利用這個面試題目複習了react render的一些邏輯,距離我被問這個問題已經有很長一段時間了,但我仍舊覺得這是個好問題,若你能完全答對表示你對於渲染的邏輯有著相當扎實的了解!搞清楚這些順序往往會讓你開發避免掉一些很微妙的問題,那麼我們明天見吧!

本文章同步發布於個人部落格,有興趣的朋友也可以來逛逛~!


上一篇
30天React練功坊-攻克常見實務/面試問題 Day20: useState with complex form
下一篇
30天React練功坊-攻克常見實務/面試問題 Day22: Simple todo-list(interview question)
系列文
30天React練功坊-攻克常見實務/面試問題30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言